/* main.c */

#include "app_inc.h"
#include "fsl_edma.h"


#define ADC0_CMD_ADDR        (uint32_t)(&(ADC0->SC1[0]))
#define ADC0_DATA_ADDR       (uint32_t)(&(ADC0->R[0]))

uint32_t gAppAdcCmd[] =
{
    ADC_SC1_ADCH(0)  | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(23) | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(26) | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(27) | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(0)  | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(23) | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(26) | ADC_SC1_AIEN_MASK,
    ADC_SC1_ADCH(27) | ADC_SC1_AIEN_MASK 
};
#define APP_ADC_CMD_COUNT  (sizeof(gAppAdcCmd)/sizeof(gAppAdcCmd[0]))

#define APP_DMA0_CONFIG {                                           \
    .SrcAddr = (uint32_t)gAppAdcCmd,                                \
    .DestAddr = ADC0_CMD_ADDR,                                      \
    .MinorLoopByteCount = sizeof(gAppAdcCmd[0]),                    \
    .SrcBusWidthMode = eEDMA_BusWidth_4Byte,                        \
    .DestBusWidthMode = eEDMA_BusWidth_4Byte,                       \
    .SrcAddrCycleMode = eEDMA_AddrCycle_Disabled,                   \
    .DestAddrCycleMode = eEDMA_AddrCycle_Disabled,                  \
    .SrcAddrIncPerTransfer = (int32_t)(sizeof(gAppAdcCmd[0])),      \
    .DestAddrIncPerTransfer = 0,                                    \
    .SrcAddrMinorLoopDoneOffset = 0,                                \
    .DestAddrMinorLoopDoneOffset = 0,                               \
    .MinorLoopCount = APP_ADC_CMD_COUNT,                            \
    .SrcAddrMajorLoopDoneOffset = -(int32_t)(sizeof(gAppAdcCmd)),   \
    .DestAddrMajorLoopDoneOffset = 0                                \
}

static void APP_InitClockGate(void);
static void APP_InitNvicInterrupts(void);
static void APP_InitAdc(void);
static bool APP_InitEdma(void);

volatile bool bAppAdcDoneFlag = false;
volatile uint32_t u32AppAdcValue;

int main(void)
{
    uint32_t i;
    
    /* Initialize the board. */
    BSP_InitSystem();
    BSP_InitStdioUART(115200);
    
    printf("\r\nHello, World\r\n");

    APP_InitClockGate();
    APP_InitNvicInterrupts();
    APP_InitAdc();
    APP_InitEdma();

    printf("\r\nPress any key to trigger the DMA for ADC Cmd.\r\n");
    
    i = 0U;
    while (1)
    {
        getchar(); /* Get a trigger from terminal. */
        
        bAppAdcDoneFlag = false;
        EDMA_SwTriggerCmd(0U); /* Trigger the DMA to transfer one ADC Cmd Word. */
        while (!bAppAdcDoneFlag) {}
        bAppAdcDoneFlag = false;
        
        printf("%8d", u32AppAdcValue);
        i++;
        if (i >= APP_ADC_CMD_COUNT)
        {
            i = 0U;
            printf("\r\n");
        }
    }
}

static void APP_InitClockGate(void)
{
    SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK
                | SIM_SCGC6_DMAMUX_MASK;
    SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
}

static void APP_InitNvicInterrupts(void)
{
    //NVIC_EnableIRQ(DMA0_IRQn);
    NVIC_EnableIRQ(ADC0_IRQn);
}

static void APP_InitAdc(void)
{
    ADC0->CFG1 = ADC_CFG1_MODE(1); /* 12-bit resolution. */
    ADC0->CFG2 = 0U;
    ADC0->SC2  = 0U;
    ADC0->SC3  = 0U;
}

static bool APP_InitEdma(void)
{
    bool bRet;
    EDMA_TransferConfig_T Edma0Config = APP_DMA0_CONFIG; /* Config the DMA for transfer ADC Cmd. */
    
    EDMA_ResetEngine();
    
    /* DMA0 for ADC Cmd. */
    DMAMUX_SetTriggerForDMA(0U, eDMAMUX_TriggerSource_Disabled);
    EDMA_ResetChannel(0U);
    bRet = EDMA_ConfigTransfer(0U, &Edma0Config);
    if (!bRet)
    {
        return false;
    }
    /* By default, the software trigger is used. */
    /*
    EDMA_SetHwTriggerEnabled(0U, true);
    DMAMUX_SetTriggerForDMA(0U, eDMAMUX_TriggerSource_PIT);
    */
    
    return bRet;
}

/*
 * IRQs.
 */
void ADC0_IRQHandler(void)
{
    u32AppAdcValue = ADC0->R[0]; /* Read result to clear COCO flag. */
    bAppAdcDoneFlag = true;;
}

/* EOF. */

